/** @file caPipeline.h
 * Functions and structures that deal with the "process pipeline" for
 * converting raw documents into output.
 */

/*
 * Licensed to the ConArtist Development Team (CADT).
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 * The CADT licenses this file to you under the Apache License, 
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CAPIPELINE_H
#define CAPIPELINE_H

#include <apr_pools.h>

#include <libxml/tree.h>

/** @defgroup PIPELINE Process Pipeline
 * Transforming a set of "raw" files into output to be served is done
 * via a pipeline. The pipeline is made up of a series of caPipe 
 * structures, each of which describes an action to perform.
 * @{
 */

/* Forward declarations... */
struct caPipe;
struct caPipeData;
struct caPipeline;
struct pipelineInstance;

/** When creating a pipe this function will be called to create the
 * caPipe structure. It will be created without any arguments set,
 * so they should be added using the caPipeAddArg function.
 */
typedef apr_status_t pipePrepareFn(struct caPipe **, 
                                   struct pipelineInstance *,
                                   xmlNodePtr);

/** Each call to process the data contained within a caPipeData structures
 * input buffer is based on this typedef. The only required argument
 * is a pointer to the caPipeData structure that is used for the input
 * and output data. when called the input data will ALWAYS be in the in
 * input buffer and any data in the output buffer can (and should) be
 * ignored.
 */
typedef apr_status_t pipeProcessFn(struct caPipeData *, struct caPipe *);

/** A pointer to one of these structures is always passed as the first 
 * argument to a function called from a caPipe structure.
 */
struct caPipeData {
    apr_pool_t  *pool;      /**< pool to use for memory allocations */
    char        *input;     /**< pointer to input buffer */
    apr_size_t   iLen;      /**< length of input buffer */
    char        *output;    /**< pointer to output buffer */
    apr_size_t   oLen;      /**< length of output buffer */
    apr_table_t *settings;  /**< Variable data created for this set of
                             * pipeline data. Should be allocated from
                             * the pool set for the structure. */
};

/** @defgroup PIPEFLAGS Pipe Flags
 * @ingroup PIPELINE
 * Pipes represent processing options as a series of OR'd flags.
 * @{
 */

#define CAP_NOSWAP   0x0001    /**< Don't swap output to input before 
                                * running this pipe */

/** @} */

/** Structure that represents a piece of the caPipeline. This structure
 * contains the information needed to execute a single function on the
 * input data, storing the output in the output fields of the supplied
 * caPipeData structure.
 */
struct caPipe {
    apr_pool_t *pool;     /**< Pool we were allocated from */

    pipeProcessFn *func;  /**< Function pointer for function to call */
    xmlNodePtr cfgNodes;  /**< Configuration nodes */
    apr_status_t rValue;  /**< Return value when function succeeds */


    void *privateData;    /**< Pointer to private data structure provided
                           * by pipe module
                           */
    int flags;            /**< CAP_ flags */
};

/** When a pipeline is created it is simply a series of instructions
 * that are enacted each time we attach a pipeline to a generator.
 */
struct pipeData {
    pipePrepareFn *func;     /**< Function to call to setup the pipe */
    xmlNodePtr cfgNodes;     /**< Pointer to xml nodes to be used to
                              *   setup the pipe */
};
 
/** The pipeline is a series of pipes that are executed sequentially,
 * with the data from one being passed into the next. This structure
 * acts as a container for a number of pipes.
 */
struct caPipeline {
    apr_pool_t *pool;        /**< Pool we were allocated from */
    char *name;              /**< name of pipeline */

    int nPipes;              /**< size of array */
    struct pipeData **pipeData; /**< Array of data to create pipes */
    char *contentType;       /**< ContentType of final output */
};

/** When a pipeline is added to a generator we create a new instance
 * of the pipeline. When we add the pipeline we create the pipes that
 * are needed for it using the specifics of the generator. Until this
 * point we dont have the details required to create the pipe correctly.
 */
struct pipelineInstance {
    struct caPipeline *pipeline; /**< Pointer to the pipeline this is an
                                  *   instance of. */
    struct caGenerator *gen; /**< Pointer to the caGenerator structure
                              * we are attached to.
                              */
    struct caPipe **pipes;   /**< array of caPipe structures */
};

/** The PI_POOL macro is used to access the pointer to the pool that should
 * be used for allocations related to the pipelineInstance object.
 */
#define PI_POOL(x)   (x)->gen->pool

/** @fn apr_status_t caPipelineInstanceCreatePipes(struct pipelineInstance *pi)
 * Create the pipes that will make up the pipeline instance. This step
 * is where we move from having simply instructions to actual pipe
 * structures that can be used.
 * @param pi Pointer to the pipeline instance
 */
apr_status_t caPipelineInstanceCreatePipes(struct pipelineInstance *);

/** @fn apr_status_t caPipelineCreate(struct caPipeline **pl, 
                                      const char *name, apr_pool_t *pool)
 * Create a new empty pipeline structure.
 * @param pl Pointer to created caPipeline structure
 * @param name Name to be assigned to pipeline
 * @param pool Pool to allocate structure from
 */
apr_status_t caPipelineCreate(struct caPipeline **, const char *,
                              apr_pool_t *);

/** @fn apr_status_t caPipelineAddPipe(struct caPipeline *pl, 
                                       struct caPipe *p)
 * Add a pipe to the end of a pipeline.
 * @param pl Pipeline to add pipe to
 * @param p  Pipe to add
 */
apr_status_t caPipelineAddPipe(struct caPipeline *pl, struct caPipe *p);

/** @fn apr_status_t caPipelineRun(struct caPipeData *data,
                                   struct pipelineInstance *pipeline)
 * Execute the various pipes contained within the pipeline using the
 * data provided by the supplied caPipeData structure.
 * @param data The data to process
 * @param pipeline The instance of a pipeline to process the data through
 */
apr_status_t caPipelineRun(struct caPipeData *, struct pipelineInstance *);

/** @fn apr_status_t caPipeRegister(const char *type, pipePrepareFn *func)
 * Register a pipe with the core server.
 * @param type String name of the pipe.
 * @param func Function to be called when the pipe is created.
 */
apr_status_t caPipeRegister(const char *, pipePrepareFn *);

/** @defgroup PIPEMOD Pipe Modules
 * @ingroup PIPELINE
 * @{    apr_status_t (*pipePrepare)(struct caPipe **, apr_pool_t *);

 */

/** Module structure that defines the required information for a
 * module providing caPipe functionality.
 */
struct caPipeModule {
    struct caModule module; /**< Basic caModule information */
    char *tag;              /**< The tag that is used to identify this
                                 module. */
    /** Function to create a caPipe structure */
    pipePrepareFn *pipePrepare;
};


/** @} */

/** @} */

#endif /* CAPIPELINE_H */
